package net.topikachu.dynamic.repository;

import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.el.ELException;
import javax.faces.FacesException;
import javax.faces.component.UIComponent;

import net.topikachu.dynamci.repository.ScreenRepository;
import net.topikachu.dynamci.screen.ComponentDescriptor;
import net.topikachu.dynamci.screen.ComponentType;
import net.topikachu.dynamci.screen.ScreenDefination;
import net.topikachu.dynamci.util.ReflectHelper;
import net.topikachu.dynamic.screen.widget.CompositeWidget;
import net.topikachu.dynamic.screen.widget.FaceletWidget;
import net.topikachu.dynamic.screen.widget.Widget;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Observer;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.Startup;

import com.sun.facelets.FaceletContext;
import com.sun.facelets.FaceletException;

@Name("widgetRepository")
@Scope(ScopeType.APPLICATION)
@AutoCreate
@Startup
public class WidgetRepository implements Serializable {

	static private Widget DUMMY_WIDGET = new Widget() {

		public Widget getChild() {
			return null;
		}

		public void apply(FaceletContext ctx, UIComponent parent)
				throws IOException, FacesException, FaceletException,
				ELException {
		}
	};

	private Map<String, Widget> allRootWidgets;

	@In
	private ScreenRepository screenRepository;

	public Widget getRootWidgetByScreen(String screenIdentify) {

		Widget widget = allRootWidgets.get(screenIdentify);
		if (widget == null) {
			ScreenDefination screenDefination = screenRepository
					.getDefination(screenIdentify);
			widget = createWidgetAndChildren(screenDefination.getRoot());
			allRootWidgets.put(screenIdentify, widget);
		}

		return widget;
	}

	@Observer("RepositoryInitializing")
	public void init() {
		allRootWidgets = new HashMap<String, Widget>();
	}

	private Widget createWidgetAndChildren(ComponentDescriptor descriptor) {

		Widget child = DUMMY_WIDGET;
		List<ComponentDescriptor> children = descriptor.getChildren();
		if (children != null) {
			if (children.size() > 1) {
				CompositeWidget compositeWidget = new CompositeWidget();
				for (ComponentDescriptor childDescriptor : children) {
					compositeWidget
							.addChild(createWidgetAndChildren(childDescriptor));
				}
				child = compositeWidget;
			} else if (children.size() == 1) {
				child = createWidgetAndChildren(children.get(0));
			}
		}

		try {
			ComponentType componentType = descriptor.getType();
			Class<Widget> clazz = ReflectHelper
					.classForName("net.topikachu.dynamic.screen.widget."
							+ componentType);
			Constructor<Widget> constructor = clazz.getConstructor(
					ComponentDescriptor.class, Widget.class);
			constructor.newInstance(descriptor, child);
			return (Widget) clazz.newInstance();
		} catch (Throwable e) {
			return new FaceletWidget(descriptor, child);
		}

		

	}

}
